#ifndef __SINGAPOREBUSSERVICESINSTOPSVIEW__
#define __SINGAPOREBUSSERVICESINSTOPSVIEW__

// [[[ begin generated region: do not modify [Generated Includes]
#include <aknview.h>
// ]]] end generated region [Generated Includes]

#include "googlepositioning.h"
#include "positionrequest.h"
#include "SingaporeBusStructures.h"
#include "AsyncFileLoader.h"
#include "IteratorControl.h"
#include "ArrivalTimeQuery.h"
#include "IrisQuery.h"
#include "SmrtQuery.h"
#include "CSingaporeBusGenericView.h"
#include "CSingaporeBusGenericView.hrh"
#include "SingaporeBusAppUi.h"
#include "DrawUtils.h"
#include "AdQuery.h"

static TInt OpenURLL(const TDesC& aUrl)
	{
	RApaLsSession apaLsSession;
	const TUid KOSSBrowserUidValue = {0x10008D39}; // 0x1020724D for S60 3rd Ed
	RBuf param;
	CleanupClosePushL(param);
	param.CreateL(1024);
	param.Format(_L("4 %S"), &aUrl);
	TUid id(KOSSBrowserUidValue);
	TApaTaskList taskList(CEikonEnv::Static()->WsSession());
	TApaTask task = taskList.FindApp(id);
	
	TInt ret = KErrNone;
	
	if(task.Exists())
	    {
		RProcess proc;
		if(proc.HasCapability(ECapabilitySwEvent, NULL))
			{
			task.BringToForeground();
			RBuf8 param8;
			CleanupClosePushL(param8);
			param8.CreateL(param.Length());
			param8.Copy(param);
		    task.SendMessage(TUid::Uid(0), param8); // UID not used
			CleanupStack::PopAndDestroy(&param8);
			}
		else
			{
			CAknErrorNote* msg = new (ELeave) CAknErrorNote(EFalse);
			msg->ExecuteLD(_L("Please close the Web browser and try again"));
			ret = KErrAccessDenied;
			}
	    }
	else
	    {
	    if(!apaLsSession.Handle())
	      {
	      User::LeaveIfError(apaLsSession.Connect());
	      }
	    TThreadId thread;
	    User::LeaveIfError(apaLsSession.StartDocument(param, KOSSBrowserUidValue, thread));
	    apaLsSession.Close();   
	    }
	CleanupStack::PopAndDestroy(&param);
	return ret;
	} 



class CSingaporeBusServicesArrivalTimeView : public CSingaporeBusGenericView<const CArrivalTimeItem*, CSingaporeBusServicesArrivalTimeView>
	{
	
public:
	RArray<const CArrivalTimeItem*> iItems;
	LManagedPtr<CAdBanner> iAdBanner;
	LManagedPtr<CAdQuery> iAdQuery;
	TBool iAdIndex;
	TInt iAdStatusCode, iAdError;

	virtual TBool FilterItem(const CArrivalTimeItem* aItem, const TDesC8& aSearchText) { return CSingaporeBusGenericHandler::FilterItem(aItem, aSearchText); }
	virtual TReal32 OrderItem(const CArrivalTimeItem* aItem) { return CSingaporeBusGenericHandler::OrderItem(aItem); }
	virtual TBool ListBoxObserver(const CArrivalTimeItem* aItem, CEikListBox* aListBox, MEikListBoxObserver::TListBoxEvent aEventType)
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		
		// Advertisement code
		if(iAdQuery.Get())
		{
		if(aListBox->CurrentItemIndex() == iAdIndex)
			{
			switch(aEventType)
				{
				case MEikListBoxObserver::EEventEnterKeyPressed:
				case MEikListBoxObserver::EEventItemClicked: // single tap
					{
					if(iAdBanner.Get() && iAdBanner->iURL)
						{
						OpenURLL(*narrowToWideLC(*iAdBanner->iURL));
						CleanupStack::PopAndDestroy();
						}
					return ETrue;
					}
				default:
					return EFalse;
				}
			}
		else
			{
			CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
			TTime currentTime;
			currentTime.HomeTime();
			TTimeIntervalMinutes intervalMinutes;
			currentTime.MinutesFrom(doc->iTimeLastAd, intervalMinutes);
			if(intervalMinutes.Int() >= 2)
				{
				doc->iTimeLastAd.HomeTime();
				iAdQuery->SubmitL( scalp::MakeFunctionL( scalp::Bind( &CSingaporeBusServicesArrivalTimeView::AdCallbackL, this, scalp::Free1, scalp::Free2, scalp::Free3, scalp::Free4 ) ) );
				}
			}
		}
		return CSingaporeBusGenericHandler::ListBoxObserver(aItem, aListBox, aEventType);
		}
	virtual TBool HandleCommandL( const CArrivalTimeItem* aItem, TInt aCommand )
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		this->iContainer->iIteratorControl->DrawDeferred();
		switch(aCommand)
			{
			case ESingaporeBusRefreshAll:
				{
				for(TInt i = 0 ; i < iItems.Count() ; ++i)
					CSingaporeBusGenericHandler::HandleCommandL(iItems[i], aCommand);
				return ETrue;
				}
			default:
				return CSingaporeBusGenericHandler::HandleCommandL(aItem, aCommand);
			}
		}
	virtual CEikListBox* CreateListBoxL()
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
		const TInt minHeight = doc->iSingaporeBusDrawItemsSG->PrimaryFont()->FontMaxHeight() + doc->iSingaporeBusDrawItemsSG->PrimaryFont()->FontMaxHeight();
		return ConstructListBoxL(
				new (ELeave) CSingaporeBusListBox,
				minHeight + (ClientRect().Height() % minHeight)/(ClientRect().Height() / minHeight)
				);
		}
	virtual void FormatItem(TDes& aBuf, const CArrivalTimeItem* aItem)
		{
		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
		aBuf.Format(_L("7\t%S"), narrowToWideLC(aItem->iService->iName));
		CleanupStack::PopAndDestroy(1);
		if(aItem->iService)
			{
			aBuf.AppendFormat(_L(" to %S"), narrowToWideLC(aItem->iService->iTo));
			CleanupStack::PopAndDestroy(1);
			}
		aBuf.AppendFormat(_L("\t"));

		switch(aItem->iRequestStatus)
			{
			case CArrivalTimeQuery::ERequestWait:
				aBuf.AppendFormat(_L("select to request"));
				break;
			case CArrivalTimeQuery::ERequestPending:
				aBuf.AppendFormat(_L("requesting..."));
				break;
			case CArrivalTimeQuery::ERequestPendingInitialization:
				aBuf.AppendFormat(_L("waiting initialisation..."));
				break;
			case CArrivalTimeQuery::ERequestCompleted:
				aBuf.AppendFormat(_L("%S \xf814 %S"), aItem->iNextBus, aItem->iSubsequentBus);
				break;
			case CArrivalTimeQuery::ERequestUnavailable:
				aBuf.AppendFormat(_L("arrival time unavailable"));
				break;
			case CArrivalTimeQuery::ERequestError:
				aBuf.AppendFormat(_L("error (%S, %S)"), aItem->iNextBus, aItem->iSubsequentBus);
				break;
			}
		aBuf.AppendFormat(_L("\t"));
		
		if(aItem->iService)
		{
		TBuf8<128> favoriteStr;
		doc->StoreFavoriteL(favoriteStr, iSelectedStation, aItem->iService);
		TBool isFavorite = EFalse;
		for(TInt i = 0 ; i < doc->iFavorites.Count() && !isFavorite; ++i)
			isFavorite = ((doc->iFavorites[i])->Find(favoriteStr) != NULL);
		if(isFavorite)
			aBuf.Append('0');
		}
		
		
		}
	
	
	void DrawItem(CSingaporeBusListBoxItemDrawer* aDrawer, const CArrivalTimeItem* aItem,
			TInt aItemIndex, const TRect& aActualItemRect,
			TBool aItemIsCurrent, TBool aViewIsEmphasized, TBool aViewIsDimmed, 
			TBool aItemIsSelected)
		{
		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
		
		CAdBanner* banner = iAdBanner.Get();

		if(iAdQuery.Get() && aItemIndex == iAdIndex)
			{
			TBuf<256> buf;
			buf.Format(_L("<Advertisement>"), iAdError, iAdStatusCode);
			if(iAdBanner.Get() && iAdBanner->iBitmap)
				doc->iSingaporeBusDrawItemsSG->DrawAdBannerL(aDrawer, iAdBanner->iBitmap, aItemIndex, aActualItemRect, aItemIsCurrent, aViewIsEmphasized, aViewIsDimmed, aItemIsSelected);
			else
				doc->iSingaporeBusDrawItemsSG->DrawAdTextL(aDrawer, buf, aItemIndex, aActualItemRect, aItemIsCurrent, aViewIsEmphasized, aViewIsDimmed, aItemIsSelected);
			}
		else
			{
			if(aItem->iStation->iStationType == TStation::ELDNormal)
				doc->iSingaporeBusDrawItemsLD->DrawBusServiceArrivalTimeItemL(aDrawer, aItem, aItemIndex, aActualItemRect, aItemIsCurrent, aViewIsEmphasized, aViewIsDimmed, aItemIsSelected);
			else
				doc->iSingaporeBusDrawItemsSG->DrawBusServiceArrivalTimeItemL(aDrawer, aItem, aItemIndex, aActualItemRect, aItemIsCurrent, aViewIsEmphasized, aViewIsDimmed, aItemIsSelected);
			}


		}
	


	
	const TStation* iSelectedStation;
	
	void ConstructL()
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		CSingaporeBusGenericView<const CArrivalTimeItem*, CSingaporeBusServicesArrivalTimeView>::ConstructL( R_SINGAPORE_BUS_SERVICES_ARRIVAL_TIME_VIEW, R_SINGAPORE_BUS_SERVICES_ARRIVAL_TIME_MARK_MENU, R_SINGAPORE_BUS_STOPS_ICONS, ESingaporeBusServicesArrivalTimeViewId );
		extern CAknToolbar* sArrivalTimeToolbar;
		sArrivalTimeToolbar = Toolbar();
		}

	void NotifyFileLoaded(const CAsyncFileLoader* aFile)
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		
		}
	
	void AdCallbackL(CAdQuery*, TInt aStatusCode, TInt aErrorCode, CAdBanner* aAdBanner)
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		iAdStatusCode = aStatusCode;
		iAdError = aErrorCode;		
		if(aStatusCode == 200 && aErrorCode == KErrNone)
			{
			iAdBanner = aAdBanner;
			if(this->iContainer)
				this->iContainer->iIteratorControl->DrawDeferred();
			}
		else delete aAdBanner;
		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
		const TInt DndTimedOut = -5120;
		if(aErrorCode == KErrNotReady || aErrorCode == KErrConnectionTerminated || aErrorCode == DndTimedOut) // not connected or connection lost
			doc->ConnectL();
		}

	void NotifyConnected()
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		for(TInt i = 0 ; i < iItems.Count() ; ++i)
			{
			if(iItems[i]->iRequestStatus == CArrivalTimeQuery::ERequestError)
				iItems[i]->iArrivalTimeQuery->SubmitL();
			}
		if(iAdQuery.Get() && iAdError != KErrNone && this->iContainer)
			iAdQuery->SubmitL( scalp::MakeFunctionL( scalp::Bind( &CSingaporeBusServicesArrivalTimeView::AdCallbackL, this, scalp::Free1, scalp::Free2, scalp::Free3, scalp::Free4 ) ) );
		}
	
	~CSingaporeBusServicesArrivalTimeView()
	{
	iItems.Close();
	}

	
		
protected:
	void DoActivateL(
		const TVwsViewId& aPrevViewId,
		TUid aCustomMessageId,
		const TDesC8& aCustomMessage )
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		CSingaporeBusGenericView<const CArrivalTimeItem*, CSingaporeBusServicesArrivalTimeView>::DoActivateL(aPrevViewId, aCustomMessageId, aCustomMessage );
		iSelectedStation = NULL;
		TPtrC8 field, value, remainder(aCustomMessage);
		while(ParseCustomMessageParamL(field, value, remainder))
			{
			if(field == _L8("id"))
				{
				CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
				TStation target = { value };
				TInt ret = doc->iStationsSortedByStationNumber.SpecificFindInOrder(&target, TLinearOrder<const TStation*>(&CSingaporeBusDocument::TLinearOrder_Station), EArrayFindMode_Any);
				iSelectedStation = (ret != KErrNotFound) ? doc->iStationsSortedByStationNumber[ret] : NULL;
				}
			}
		iAdIndex = KErrNotFound;
		InitializeList();
		RestoreViewStateL(aCustomMessage);
		{
		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
		if(!doc->iScheduleRequestManual)
			CSingaporeBusGenericView<const CArrivalTimeItem*, CSingaporeBusServicesArrivalTimeView>::HandleCommandL(ESingaporeBusRefreshAll);
		}
		}
	void DoDeactivate()
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		this->SetEmptyUnderlyingL();
		for(TInt i = 0 ; i < iItems.Count() ; ++i)
			delete iItems[i];
		iItems.Reset();
		CSingaporeBusGenericView<const CArrivalTimeItem*, CSingaporeBusServicesArrivalTimeView>::DoDeactivate();
		}

	
	void StoreViewStateL(TDes8& aCustomMessage)
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		StoreCustomMessageParamL(aCustomMessage, _L8("id"), _L8("%S"), &iSelectedStation->iStationNumber);
		CSingaporeBusGenericView<const CArrivalTimeItem*, CSingaporeBusServicesArrivalTimeView>::StoreViewStateL(aCustomMessage);
		}
	
	void InitializeList()
		{
	TFunTrace funTrace(__PRETTY_FUNCTION__);

		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
		if(!iSelectedStation) return;
		if(!doc->iServicesSortedByServiceKey.Count()) return; // confirmation that all information is loaded
		this->SetEmptyUnderlyingL();
		for(TInt i = 0 ; i < iItems.Count() ; ++i)
			delete iItems[i];
		iItems.Reset();
		for(TInt j = iSelectedStation->iServicesBeg ; j < iSelectedStation->iServicesEnd ; ++j)
			{
			const TDesC8& serviceKey = doc->iStationServiceKeys[j];
			const TService* service = NULL;
			{
			TBuf8<15> serviceKeyUpper(serviceKey);
			serviceKeyUpper.UpperCase();
			TService target = { serviceKeyUpper };
			TInt ret = doc->iServicesSortedByServiceKey.SpecificFindInOrder(&target, TLinearOrder<const TService*>(&CSingaporeBusDocument::TLinearOrder_Service), EArrayFindMode_Any);
			service = (ret != KErrNotFound) ? doc->iServicesSortedByServiceKey[ret] : NULL;
			}
			if(service && iSelectedStation)
				iItems.AppendL( CSingaporeBusGenericHandler::NewArrivalTimeItemL(iSelectedStation, service, this) );
			}

		// Advertisement code
		if(iSelectedStation->iStationType == TStation::ELDNormal) //Ads only for London
		{
		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();
		iAdQuery = new (ELeave) CAdQuery( doc->iAdSession.Get() );
		iAdQuery->SetCoordinate( iSelectedStation->iCoord );
		iAdQuery->SubmitL( scalp::MakeFunctionL( scalp::Bind( &CSingaporeBusServicesArrivalTimeView::AdCallbackL, this, scalp::Free1, scalp::Free2, scalp::Free3, scalp::Free4 ) ) );
		iAdIndex = 0;
		doc->iTimeLastAd.HomeTime();
		iItems.Insert( CSingaporeBusGenericHandler::NewArrivalTimeItemL(iSelectedStation, iItems[0]->iService, this), iAdIndex );
		}
		
		if(iItems.Count() > 0)
			this->SetUnderlyingL(
					new (ELeave) CArrayIterator<const CArrivalTimeItem*>(&iItems[0], iItems.Count())
					);	
		else
			{
			this->SetEmptyUnderlyingL();
			iContainer->iIteratorControl->iListBox->View()->SetListEmptyTextL(_L("No bus found at this stop"));
			iContainer->iIteratorControl->iListBox->DrawDeferred();
			}
		}
	
		
	};

#endif // __SINGAPOREBUSSERVICESINSTOPSVIEW__
